package zhishuang.wang.sansi.tools.json.exception;

/**
 * @Author Zhishuang.Wang
 * @Date 2023/7/5 11:19
 * @Email 1406110602@qq.com
 */

import org.apache.commons.lang3.exception.ExceptionUtils;

public class FormativeException extends RuntimeException {
    private int[] indices;
    private int usedCount;
    private String message;
    private transient Throwable throwable;

    public FormativeException() {
    }

    public FormativeException(String message) {
        this.message = message;
    }

    public FormativeException(Throwable cause) {
        this.throwable = cause;
        this.message = ExceptionUtils.getStackTrace(this.throwable);
    }

    public FormativeException(String format, Object... arguments) {
        this.init(format, arguments);
        this.fillInStackTrace();
        this.message = this.formatMessage(format, arguments);
        if (this.throwable != null) {
            this.message = this.message + System.lineSeparator() + ExceptionUtils.getStackTrace(this.throwable);
        }

    }

    public String getMessage() {
        return this.message;
    }

    public String toString() {
        String s = this.getClass().getName();
        String message = this.getMessage();
        return message != null ? s + ": " + message : s;
    }

    private void init(String format, Object... arguments) {
        int len = Math.max(1, format == null ? 0 : format.length() >> 1);
        this.indices = new int[len];
        int placeholders = ParameterFormatter.countArgumentPlaceholders2(format, this.indices);
        this.initThrowable(arguments, placeholders);
        this.usedCount = Math.min(placeholders, arguments == null ? 0 : arguments.length);
    }

    private void initThrowable(Object[] params, int usedParams) {
        if (params != null) {
            int argCount = params.length;
            if (usedParams < argCount && this.throwable == null && params[argCount - 1] instanceof Throwable) {
                this.throwable = (Throwable)params[argCount - 1];
            }
        }

    }

    private String formatMessage(String format, Object... arguments) {
        StringBuilder stringBuilder = new StringBuilder();
        if (this.indices[0] < 0) {
            ParameterFormatter.formatMessage(stringBuilder, format, arguments, this.usedCount);
        } else {
            ParameterFormatter.formatMessage2(stringBuilder, format, arguments, this.usedCount, this.indices);
        }

        return stringBuilder.toString();
    }
}
